﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data;

namespace OMSService
{
    public class OrderManager
    {
        #region CRUD

        public static OrderModel New(int customerId, decimal totalPrice, string status,
            DateTime dateOfOrdering, DateTime prefDeliveryDate, DateTime deliveryDate, List<OrderItemModel> orderItems, int merchId)
        {
            OrderModel orderModel = new OrderModel(customerId, totalPrice, status, dateOfOrdering,
                prefDeliveryDate, deliveryDate, orderItems, merchId);
            return orderModel;
        }

        public static int Save(OrderModel orderModel)
        {
            int id;
            try
            {
                using (OMSModelContainer context = new OMSModelContainer())
                {
                    Order order = new Order
                    {
                        OrderNumber = orderModel.OrderNumber,
                        TotalPrice = orderModel.TotalPrice,
                        Status = orderModel.Status,
                        DateOfOrdering = orderModel.DateOfOrdering,
                        PrefDeliveryDate = orderModel.PrefDeliveryDate,
                        DeliveryDate = orderModel.DeliveryDate,
                        CreditCard = new CreditCard{
                            Type = orderModel.Card._Type,
                            Number = orderModel.Card.Number,
                            Cv2 = orderModel.Card.Cv2,
                            ExpiryDate = orderModel.Card.ExpiryDate,
                            StartDate = orderModel.Card.StartDate,
                            IssueNumber = orderModel.Card.IssueNumber
                        }
                    };
                    User user = context.Users.Where(m => m.Id == orderModel.CustomerId).FirstOrDefault();
                    Customer customer = user.Customer;
                    //Customer customer = context.Customers.Where(m => m.Id == orderModel.CustomerId).FirstOrDefault();
                    context.Orders.AddObject(order);
                    customer.Orders.Add(order);
                    context.Customers.ApplyCurrentValues(customer);
                    if (orderModel.MerchId != null && orderModel.MerchId != 0)
                    {
                        User merch = context.Users.Where(m => m.Id == orderModel.MerchId).FirstOrDefault();
                        merch.Order.Add(order);
                        context.Users.ApplyCurrentValues(merch);
                    }
                    context.SaveChanges();
                    id = order.Id;
                }
            }
            catch (DataException ex)
            {
                return -1;
            }
            return id;
        }

        public static CreditCardModel GetCreditCard(int id)
        {
            CreditCardModel creditCardModel;
            using (OMSModelContainer context = new OMSModelContainer())
            {
                Order order = (from m in context.Orders where m.Id == id select m).FirstOrDefault();
                CreditCard card = order.CreditCard;
                creditCardModel = new CreditCardModel(card);
            }
            return creditCardModel;
        }

        public static bool AddOrderItem(int orderId, OrderItemModel orderItemModel)
        {
            try
            {
                using (OMSModelContainer context = new OMSModelContainer())
                {
                    Order order = (from m in context.Orders where m.Id == orderId select m).FirstOrDefault();
                    Item item = (from m in context.Items where m.Id == orderItemModel.ItemId select m).FirstOrDefault();
                    if (item.Quantity < orderItemModel.Quantity)
                    {
                        throw new DataException();
                    }
                    else
                    {
                        item.Quantity -= orderItemModel.Quantity;
                    }
                    OrderItem orderItem = new OrderItem
                    {
                        Price = item.Price * orderItemModel.Quantity,
                        Quantity = orderItemModel.Quantity,
                        Dimension = orderItemModel.Dimension,
                        Item = item
                    };
                    order.TotalPrice += orderItem.Price;
                    order.OrderItems.Add(orderItem);
                    context.OrderItems.AddObject(orderItem);
                    context.Items.ApplyCurrentValues(item);
                    context.Orders.ApplyCurrentValues(order);
                    context.SaveChanges();
                }
            }
            catch (DataException ex)
            {
                return false;
            }
            return true;
        }

        public static int Create(int customerId, decimal totalPrice, string status,
            DateTime dateOfOrdering, DateTime prefDeliveryDate, DateTime deliveryDate, 
            List<OrderItemModel> orderItems, int merchId)
        {
            OrderModel order = New(customerId, totalPrice, status,
            dateOfOrdering, prefDeliveryDate, deliveryDate, orderItems, merchId);
            return (Save(order));
        }

        public static OrderModel GetById(int id)
        {
            Order order;
            OrderModel orderModel;
            using (OMSModelContainer context = new OMSModelContainer())
            {
                order = (from m in context.Orders where m.Id == id select m).FirstOrDefault();
                orderModel = new OrderModel(order);
            }
            return orderModel;
        }

        public static List<OrderModel> GetAll()
        {
            List<Order> orders;
            using (OMSModelContainer context = new OMSModelContainer())
            {
                orders = context.Orders.ToList();
            }
            List<OrderModel> tmpOrders = new List<OrderModel>();
            foreach (Order i in orders)
            {
                tmpOrders.Add(new OrderModel(i));
            }
            return tmpOrders;
        }

        public static bool Update(OrderModel orderModel)
        {
            try
            {
                using (OMSModelContainer context = new OMSModelContainer())
                {
                    Order order = (from m in context.Orders where m.Id == orderModel.Id select m).FirstOrDefault();
                    //order.CustomerId = orderModel.CustomerId;
                    //order.TotalPrice = orderModel.TotalPrice;
                    order.Status = orderModel.Status;
                    //order.DateOfOrdering = orderModel.DateOfOrdering;
                    if (orderModel.PrefDeliveryDate > DateTime.MinValue)
                    {
                        order.PrefDeliveryDate = orderModel.PrefDeliveryDate;
                    }
                    if (orderModel.DeliveryDate > DateTime.MinValue)
                    {
                        order.DeliveryDate = orderModel.DeliveryDate;
                    }
                    if (orderModel.OrderNumber != "")
                    {
                        order.OrderNumber = orderModel.OrderNumber;
                    }
                    if (orderModel.Card != null)
                    {
                        order.CreditCard.Type = orderModel.Card._Type;
                        order.CreditCard.Number = orderModel.Card.Number;
                        order.CreditCard.Cv2 = orderModel.Card.Cv2;
                        order.CreditCard.ExpiryDate = orderModel.Card.ExpiryDate;
                        order.CreditCard.StartDate = orderModel.Card.StartDate;
                        order.CreditCard.IssueNumber = orderModel.Card.IssueNumber;
                    }
                    if (orderModel.MerchId != null && orderModel.MerchId != 0 && orderModel.MerchId != order.MerchId)
                    {
                        User merch = context.Users.Where(m => m.Id == orderModel.MerchId).FirstOrDefault();
                        merch.Order.Add(order);
                        context.Users.ApplyCurrentValues(merch);
                    }
                    context.Orders.ApplyCurrentValues(order);
                    context.SaveChanges();
                }
            }
            catch (DataException ex)
            {
                return false;
            }
            return true;
        }

        public static bool Delete(int id)
        {
            try
            {
                using (OMSModelContainer context = new OMSModelContainer())
                {
                    Order order = (from m in context.Orders where m.Id == id select m).First();
                    Item item;
                    if (order.Status == "created")
                    {
                        foreach (var orderItem in order.OrderItems)
                        {
                            item = orderItem.Item;
                            item.Quantity += orderItem.Quantity;
                            context.Items.ApplyCurrentValues(item);
                        }
                    }
                    context.Orders.DeleteObject(order);
                    context.SaveChanges();
                }
            }
            catch (DataException ex)
            {
                return false;
            }
            return true;
        }

        public static List<OrderModel> GetAllOrders()
        {
            List<OrderModel> orderModels = new List<OrderModel>();
            List<Order> orders = new List<Order>();
            using (OMSModelContainer context = new OMSModelContainer())
            {
                orders = context.Orders.ToList();
                foreach (var order in orders)
                {
                    orderModels.Add(new OrderModel(order));
                }
            }
            return orderModels;
        }

        public static List<OrderModel> GetCustomerOrders(int userId)
        {
            List<Order> orders = new List<Order>();
            List<OrderModel> orderModels = new List<OrderModel>();
            using (OMSModelContainer context = new OMSModelContainer())
            {
                User user = context.Users.Where(m => m.Id == userId).FirstOrDefault();
                Customer customer = user.Customer;
                orders = customer.Orders.ToList();
                foreach (var order in orders)
                {
                    orderModels.Add(new OrderModel(order));
                }
            }
            return orderModels;
        }

        #region Filter

        public static List<OrderModel> Filter(string field, string pattern)
        {
            pattern = pattern.ToLower();
            List<OrderModel> orderModels = new List<OrderModel>();
            List<Order> orders = new List<Order>();
            using (OMSModelContainer context = new OMSModelContainer())
            {
                switch(field)
                {
                    case "ordername":
                        orders = context.Orders.Where(m => m.OrderNumber.ToLower().StartsWith(pattern)).ToList();
                        break;
                    case "status":
                        orders = context.Orders.Where(m => m.Status.ToLower().StartsWith(pattern)).ToList();
                        break;
                    case "assignee":
                        List<User> users = context.Users.Where(m => m.FirstName.ToLower().StartsWith(pattern) ||
                            m.LastName.ToLower().StartsWith(pattern)).ToList();
                        foreach(var user in users)
                        {
                            orders.AddRange(user.Order);
                        }
                        break;
                }
                foreach (var order in orders)
                {
                    orderModels.Add(new OrderModel(order));
                }
            }
            return orderModels;
        }

        #endregion

        #endregion
    }
}